package index;

import Transaction.Transaction;
import Common.GoggleDB;
import storage.data.Page;
import storage.data.PageID;
import heap.HFPage;
import heap.RID;

public class BTPage extends HFPage {

	int keyType;

	public BTPage(PageID pageno, int keyType) throws Exception {
		super();
		GoggleDB.bufferMgr.pinPage(pageno, this, false);
		this.keyType = keyType;
	}

	public BTPage(Page page, int keyType) {
		super(page);
		this.keyType = keyType;
	}

	/**
	 * new a page and associate the BTPage instance with the page insctance
	 * 
	 * @param keyType
	 * @throws Exception
	 */
	public BTPage(int keyType,Transaction tx,String table) throws Exception {
		super();
		Page apage = new Page();
		PageID pageId = GoggleDB.storageInterface.allocatePage(1);
		GoggleDB.bufferMgr.pinPage(pageId, apage, true);
		this.init(pageId, apage,tx,table);
		this.keyType = keyType;
	}

	/*
	 * Only the slot directory is rearranged.
	 */
	public RID insertRecord(KeyDataEntry entry,Transaction tx,String table) throws Exception {
//		int i;
//		short nType;
//		RID rid;
//		byte[] record;
//
//		record = BT.getBytesFromEntry(entry);
//		rid = super.insertRecord(record,tx,table,curPage);
//		if (rid == null) {
//			return null;
//		}
// 
//		if (entry.data instanceof LeafData) {
//			nType = NodeType.LEAF;
//		} else {
//			nType = NodeType.INDEX;
//		}
//		Global.timer.start("insertCH");
//		for (i = getSlotCnt(tx,table) - 1; i > 0; i--) {
//			KeyClass keyi, keyiplus1;
//
//			keyi = BT.getEntryFromBytes(getData(), getSlotOffset(i,tx,table),
//					getSlotLength(i,tx,table), keyType, nType,tx,table).key;
//			keyiplus1 = BT.getEntryFromBytes(getData(), getSlotOffset(i - 1,tx,table),
//					getSlotLength(i - 1,tx,table), keyType, nType,tx,table).key;
//
//			if (BT.KeyCompare(keyi, keyiplus1) < 0) {
//				// switch slots:
//				int ln, off;
//				ln = getSlotLength(i,tx,table);
//				off = getSlotOffset(i,tx,table);
//				setSlot(i, getSlotLength(i - 1,tx,table), getSlotOffset(i - 1,tx,table),tx,table,curPage);
//				setSlot(i - 1, ln, off,tx,table,curPage);
//			} else {
//				// end insertion sort
//				break;
//			}
//
//		}
//		Global.timer.end("insertCH");
//		rid.slotNo = i;
//		return rid;
//		Global.timer.start("insertNM");
		int i;
		short nType;
		RID rid;
		byte[] record;

		if (entry.data instanceof LeafData) {
			nType = NodeType.LEAF;
		} else {
			nType = NodeType.INDEX;
		}

//		System.out.println("ovv1");
//		for (i = getSlotCnt(tx, table) - 1; i >= 0; i--) {
//			KeyClass keyi;
//			keyi = BT.getEntryFromBytes(getData(), getSlotOffset(i, tx, table),
//					getSlotLength(i, tx, table), keyType, nType, tx, table).key;
//			System.out.println(((IntegerKey) keyi).getKey());
//
//		}
//		System.out.println("endovv1");

		
		record = BT.getBytesFromEntry(entry);
//		Global.timer.start("insertur");
		rid = super.insertRecord(record, tx, table, curPage);
//		Global.timer.end("insertur");
		if (rid == null) {
			return null;
		}

//		System.out.println("ovv");
//		for (i = getSlotCnt(tx, table) - 1; i >= 0; i--) {
//			KeyClass keyi;
//			keyi = BT.getEntryFromBytes(getData(), getSlotOffset(i, tx, table),
//					getSlotLength(i, tx, table), keyType, nType, tx, table).key;
//			System.out.println(((IntegerKey) keyi).getKey());
//
//		}
		//System.out.println("endovv");
		KeyClass key = entry.key;
		int count = getSlotCnt(tx, table);
		//System.out.println("cout"+ " "+count);
		int left = 0;
		int right = count - 1;
		int middle = (left + right) / 2;
		
//		Global.timer.start("insertCH");
		if(right<left){
			middle = 0;
		}else {
		
			while (true) {
				KeyClass keymiddle;
				//System.out.println("inmiddle:" + middle);
				middle = (left + right) / 2;
				keymiddle = BT.getEntryFromBytes(getData(), getSlotOffset(
						middle, tx, table), getSlotLength(middle, tx, table),
						keyType, nType, tx, table).key;
				if (BT.KeyCompare(key, keymiddle) < 0) {
					right = middle;
				} else {
					left = middle+1;
				}
				if (right <= left) {
					middle = right;
					//System.out.println("MIDDLEHAHA"+" "+middle);
					break;
				}

			}
		}
//		Global.timer.end("insertCH");
		//middle = (left + right) / 2;
		//System.out.println("middle:" + middle);
		// setSlot(middle,EMPTY_SLOT,0,tx,table,curPage);
		
		
		int pos1 = DPFIXED + middle * SIZE_OF_SLOT;
		int pos2 = DPFIXED + (middle + 1) * SIZE_OF_SLOT;
		int len = (count - middle) * SIZE_OF_SLOT;
		// System.out.println("count-middle:"+len);
		int offset = getSlotOffset(count - 1, tx, table);
		tx.setBytes(table, curPage, data, pos1, data, pos2, len);
		setSlot(middle, record.length, offset, tx, table, curPage);
		
		// int count = getSlotCnt(tx,table);
		// int left = 0;
		// int right =count-1 ;
		// KeyClass key = entry.key;
		// int middle=(left+right)/2;
		// while(left<=right) {
		// KeyClass keymiddle;
		// middle=(left+right)/2;
		// keymiddle = BT.getEntryFromBytes(getData(),
		// getSlotOffset(middle,tx,table),
		// getSlotLength(middle,tx,table), keyType, nType,tx,table).key;
		// if(BT.KeyCompare(key, keymiddle)<0) {
		// right = middle-1;
		// } else {
		// left = middle+1;
		// }
		//
		//			
		//			
		// }
		// //System.out.println("middle:"+middle);
		// int pos1 = DPFIXED+middle*SIZE_OF_SLOT;
		// int pos2 = DPFIXED+(middle+1)*SIZE_OF_SLOT;
		// int len = (count-middle)*SIZE_OF_SLOT;
		// //System.out.println("count-middle:"+len);
		// tx.setBytes(table, curPage, data, pos1, data, pos2, len);
		// setSlot(middle,EMPTY_SLOT,0,tx,table,curPage);
		// record = BT.getBytesFromEntry(entry);
		// // rid = super.insertRecord(record,tx,table,curPage);
		//		
		// int spaceNeeded = SIZE_OF_SLOT;
		// freeSpace -= spaceNeeded;
		//		
		// Convert.setShortValue(freeSpace, FREE_SPACE, data,tx,table,curPage);
		// slotCount++;
		// //System.out.println("slotCount:"+slotCount);
		// Convert.setShortValue(slotCount, SLOT_CNT, data,tx,table,curPage);
		// rid = super.insertRecord(record,tx,table,curPage);
		// if (rid == null) {
		// return null;
		// }
//		System.out.println("start");
//		for (i = getSlotCnt(tx, table) - 1; i >= 0; i--) {
//			KeyClass keyi;
//			keyi = BT.getEntryFromBytes(getData(), getSlotOffset(i, tx, table),
//					getSlotLength(i, tx, table), keyType, nType, tx, table).key;
//			System.out.println(((IntegerKey) keyi).getKey());
//
//		}
//		System.out.println("end");

		// Global.timer.start("insertCH");
		// for (i = getSlotCnt(tx,table) - 1; i > 0; i--) {
		// KeyClass keyi, keyiplus1;
		//
		// keyi = BT.getEntryFromBytes(getData(), getSlotOffset(i,tx,table),
		// getSlotLength(i,tx,table), keyType, nType,tx,table).key;
		// keyiplus1 = BT.getEntryFromBytes(getData(), getSlotOffset(i -
		// 1,tx,table),
		// getSlotLength(i - 1,tx,table), keyType, nType,tx,table).key;
		//
		// if (BT.KeyCompare(keyi, keyiplus1) < 0) {
		// // switch slots:
		// int ln, off;
		// ln = getSlotLength(i,tx,table);
		// off = getSlotOffset(i,tx,table);
		// setSlot(i, getSlotLength(i - 1,tx,table), getSlotOffset(i -
		// 1,tx,table),tx,table,curPage);
		// setSlot(i - 1, ln, off,tx,table,curPage);
		// } else {
		// // end insertion sort
		// break;
		// }
		//
		// }
		// System.out.println("i:"+i+" "+getSlotCnt(tx,table));
		 
		// rid.slotNo = i;
		rid.slotNo = middle;
//		 Global.timer.end("insertNM");
		return rid;
	}

	public boolean deleteSortedRecord(RID rid,Transaction tx,String table) throws Exception {
		//Global.timer.start("delete");
		int slotNo=deleteRecord(rid,tx,table,curPage);
		compactSlotDir(tx,table,curPage,slotNo);
		//Global.timer.end("delete");
		return true;

	}
	
	protected int numberOfRecords(Transaction tx,String table) throws Exception {
		return getSlotCnt(tx,table);
	}

}
